{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Export Network as Touchstone File"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Frequently a `Network` is required to be saved as a [Touchstone file](https://en.wikipedia.org/wiki/Touchstone_file) so that it can be imported into another program such as [Keysight ADS](https://www.keysight.com/zz/en/products/software/pathwave-design-software/pathwave-advanced-design-system.html) or [Microwave Office](https://www.cadence.com/en_US/home/tools/system-analysis/rf-microwave-design/awr-design-environment-platform.html). The `Network.write_touchstone()` method allows `Network` objects to be exported in the appropriate format."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "import skrf as rf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "In this example, we are going to first generate a random 2-port `Network` and export the data as a Touchstone file using all the default arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "!Default output\n",
      "! Created with skrf (http://scikit-rf.org).\n",
      "# GHz S RI R 50.0 \n",
      "!freq ReS11 ImS11 ReS21 ImS21 ReS12 ImS12 ReS22 ImS22\n",
      "1.0 -0.464865151852476 0.4502139349896557 -0.946087157816933 -0.774157144858624 0.22978320604401903 -0.015382277631633245 -0.5143243821327415 0.5414888218758449\n",
      "5.9 -0.7714731941571016 0.5035362767937888 -0.13676846127948927 -0.28407348971702495 0.22574007371745886 0.7585739185331353 -0.10651147209906475 0.8017532911041758\n",
      "10.8 0.9283594792475798 -0.949741920331475 0.0013830072200151644 0.5869045175861258 -0.7303982230754289 0.4182901609474474 0.5005946980290608 -0.7192362826596026\n",
      "15.7 0.05196345220484089 0.9250542904689592 -0.9756169835079893 -0.6532005774023946 0.29678736213869095 -0.2743856183602864 0.2781155976701659 0.36062628422326837\n",
      "20.6 -0.07332329228960388 0.6134822411048317 -0.5177662945200454 0.41284206902464593 -0.2849256858620177 -0.5010232817863058 0.10007939815281519 -0.7011091912436347\n",
      "25.5 0.30846454726129147 -0.2866491167667229 -0.8623359516384592 0.6450662462360961 -0.43036099270200423 -0.342207252231161 0.39369055828649846 0.2474543341740585\n",
      "30.4 0.9145795203794396 0.44609982646636714 0.4880768496247685 0.22450675141896115 0.32412739749113073 0.8792809268192112 -0.30411660385369754 -0.9493881130068704\n",
      "35.3 -0.24284888674338645 0.5629931583833381 -0.25560444449996966 -0.47942310384730313 -0.5503294379329955 0.5260341997912912 0.22181324903183786 -0.27354385834163275\n",
      "40.2 -0.15445158678019144 0.1402545231555048 0.05233201867297299 0.9262610033960388 0.08012592129752671 0.6362204417635848 0.9853804482302841 0.924566084120912\n",
      "45.1 -0.24518734266073183 -0.30977957882926366 -0.5973235149690603 -0.9127315640504685 0.7676585384502421 0.613791431633252 0.9912077531024381 -0.17175649696500606\n",
      "50.0 0.9023961597916488 0.8155000860198645 -0.2374313674378361 -0.8139274742596938 0.5362539112613807 -0.8023396937590226 0.5812260184801696 -0.8008646540965754\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Handle for random generator\n",
    "rand_gen = np.random.default_rng()\n",
    "\n",
    "# Set the number of points\n",
    "ports = 2\n",
    "\n",
    "# Generate the frequency object\n",
    "points = 11\n",
    "freq = rf.Frequency(1, 50, points, \"GHz\")\n",
    "\n",
    "# Create random data to fill the Network\n",
    "s_random = rand_gen.uniform(-1, 1, (freq.npoints, ports, ports)) + 1j * rand_gen.uniform(\n",
    "    -1, 1, (freq.npoints, ports, ports)\n",
    ")\n",
    "\n",
    "# Generate the Network object\n",
    "ntwk = rf.Network(s=s_random, frequency=freq, name=\"test_ntwk\")\n",
    "ntwk.comments = \"Default output\"\n",
    "\n",
    "# Define the save location\n",
    "filepath = Path(f\"test_network.s{ports}p\")\n",
    "\n",
    "# Save the Network as a touchstone file using the default arguments\n",
    "print(ntwk.write_touchstone(filepath, return_string=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "In this example, we are going to export the same 2-port `Network` as a Touchstone file, but use the formatting strings to format the columns of the resulting file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "!Formatted output\n",
      "! Created with skrf (http://scikit-rf.org).\n",
      "# GHz S DB R 50.0 \n",
      "!freq dBS11 angS11 dBS21 angS21 dBS12 angS12 dBS22 angS22\n",
      "1.00000    \t  -3.78001 \t 135.91728 \t   1.74467 \t-140.70748 \t -12.75422 \t  -3.82981 \t  -2.53568 \t 133.52619\n",
      "5.90000    \t  -0.71236 \t 146.86774 \t -10.02599 \t-115.70870 \t  -2.03153 \t  73.42779 \t  -1.84321 \t  97.56733\n",
      "10.80000   \t   2.46464 \t -45.65229 \t  -4.62863 \t  89.86499 \t  -1.49692 \t 150.20076 \t  -1.14698 \t -55.16175\n",
      "15.70000   \t  -0.66297 \t  86.78488 \t   1.39407 \t-146.19668 \t  -7.86827 \t -42.75398 \t  -6.83192 \t  52.36053\n",
      "20.60000   \t  -4.18236 \t  96.81565 \t  -3.58010 \t 141.43282 \t  -4.78591 \t-119.62635 \t  -2.99668 \t -81.87623\n",
      "25.50000   \t  -7.51247 \t -42.90062 \t   0.64358 \t 143.20185 \t  -5.19538 \t-141.50957 \t  -6.65092 \t  32.15143\n",
      "30.40000   \t   0.15134 \t  26.00150 \t  -5.39670 \t  24.70160 \t  -0.56410 \t  69.76471 \t  -0.02690 \t-107.76177\n",
      "35.30000   \t  -4.24885 \t 113.33311 \t  -5.29913 \t-118.06431 \t  -2.36891 \t 136.29304 \t  -9.06483 \t -50.96184\n",
      "40.20000   \t -13.61245 \t 137.75801 \t  -0.65149 \t  86.76633 \t  -3.85950 \t  82.82193 \t   2.61453 \t  43.17627\n",
      "45.10000   \t  -8.06652 \t-128.36125 \t   0.75501 \t-123.20214 \t  -0.15005 \t  38.64454 \t   0.05178 \t  -9.83060\n",
      "50.00000   \t   1.70074 \t  42.10428 \t  -1.43361 \t-106.26253 \t  -0.30902 \t -56.24271 \t  -0.09125 \t -54.02980\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Get a copy of the network\n",
    "ntwk_formatted = ntwk.copy()\n",
    "ntwk_formatted.comments = \"Formatted output\"\n",
    "\n",
    "# Define the save location\n",
    "formatted_filepath = Path(f\"test_network_formatted.s{ports}p\")\n",
    "\n",
    "# Save the Network as a touchstone file using the string formatting options\n",
    "freq_fmt = \"{:<8.3f}\"\n",
    "data_fmt = \"\\t{:>8.3f}\"\n",
    "print(\n",
    "    ntwk_formatted.write_touchstone(\n",
    "        formatted_filepath,\n",
    "        form=\"db\",\n",
    "        return_string=True,\n",
    "        format_spec_freq=freq_fmt,\n",
    "        format_spec_A=data_fmt,\n",
    "        format_spec_B=data_fmt,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example, we are going to export a new 2-port `Network` as a Touchstone file, but we're going to include random noise data and format those output columns as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "!Formatted output with noise data\n",
      "! Created with skrf (http://scikit-rf.org).\n",
      "# GHz S DB R 50.0 \n",
      "!freq dBS11 angS11 dBS21 angS21 dBS12 angS12 dBS22 angS22\n",
      "1.00000    \t  -0.91328 \t-130.97542 \t  -1.29884 \t 130.51454 \t  -4.26300 \t-173.56091 \t  -1.87356 \t-113.17161\n",
      "5.90000    \t  -1.46165 \t  34.91404 \t  -5.12067 \t  43.04405 \t  -0.70823 \t-141.59246 \t  -2.14551 \t  47.87232\n",
      "10.80000   \t  -7.68630 \t  31.44550 \t   1.37477 \t -49.54463 \t -39.56968 \t -16.58557 \t  -5.65258 \t  -8.49307\n",
      "15.70000   \t  -0.90550 \t-136.21873 \t  -1.18593 \t  15.14162 \t  -1.69316 \t-161.16082 \t -23.72235 \t-165.91385\n",
      "20.60000   \t  -9.51858 \t  89.43189 \t  -4.74431 \t  25.90892 \t   1.38186 \t 140.40619 \t  -3.82659 \t   6.48215\n",
      "25.50000   \t  -0.03824 \t -91.89634 \t   1.75464 \t  39.54287 \t  -2.64012 \t-148.02961 \t  -6.09412 \t 177.52691\n",
      "30.40000   \t  -1.85579 \t  11.21887 \t   0.24374 \t-156.97826 \t   1.38966 \t 134.87892 \t  -4.55095 \t-136.33491\n",
      "35.30000   \t -18.78104 \t  17.95128 \t   1.71843 \t -54.35505 \t -12.79699 \t-123.19957 \t  -3.37591 \t 121.12044\n",
      "40.20000   \t  -3.73726 \t -41.69093 \t  -0.48082 \t-113.51842 \t  -1.53413 \t 132.51577 \t -23.70471 \t 172.04825\n",
      "45.10000   \t -11.28388 \t-116.27157 \t  -9.69757 \t 104.96040 \t  -4.38896 \t-160.06974 \t   0.49972 \t -50.23027\n",
      "50.00000   \t  -4.56446 \t 115.81996 \t -15.72494 \t 114.38783 \t  -2.05009 \t  81.27382 \t   1.60838 \t -54.51620\n",
      "! Noise Data\n",
      "! freq\tnf_min_db\tmagGOpt\tdegGOpt\tRn_eff\n",
      "1.00000    \t   3.83480 \t   0.30042 \t  24.54642 \t   0.01791 \n",
      "5.90000    \t   4.89486 \t   0.90514 \t  55.03904 \t   0.01656 \n",
      "10.80000   \t   5.62803 \t   0.99515 \t -69.60951 \t   0.00183 \n",
      "15.70000   \t   0.14024 \t   0.67099 \t-110.38925 \t   0.01086 \n",
      "20.60000   \t   2.69752 \t   0.16396 \t  80.84681 \t   0.00130 \n",
      "25.50000   \t   1.47690 \t   0.95158 \t 143.39918 \t   0.00701 \n",
      "30.40000   \t   3.60385 \t   0.16757 \t  95.22127 \t   0.00777 \n",
      "35.30000   \t   2.89029 \t   0.74515 \t-102.91751 \t   0.00525 \n",
      "40.20000   \t   8.65540 \t   0.74206 \t -46.60443 \t   0.00098 \n",
      "45.10000   \t   7.21090 \t   0.51109 \t -38.36113 \t   0.01287 \n",
      "50.00000   \t   6.95480 \t   0.67592 \t -29.05023 \t   0.01013 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Create random data to fill the Network\n",
    "s_random = rand_gen.uniform(-1, 1, (freq.npoints, ports, ports)) + 1j * rand_gen.uniform(\n",
    "    -1, 1, (freq.npoints, ports, ports)\n",
    ")\n",
    "\n",
    "# Create random noise data to fill the Network\n",
    "nfmin_db_random = rand_gen.uniform(0, 10, freq.npoints)\n",
    "g_opt_random = rand_gen.uniform(-1, 1, freq.npoints) + 1j * rand_gen.uniform(-1, 1, freq.npoints)\n",
    "rn_random = rand_gen.uniform(size=freq.npoints)\n",
    "\n",
    "# Generate the Network object\n",
    "noisy_ntwk = rf.Network(s=s_random, frequency=freq, name=\"test_noisy_ntwk\")\n",
    "noisy_ntwk.comments = \"Formatted output with noise data\"\n",
    "\n",
    "# Add the noise data\n",
    "noisy_ntwk.set_noise_a(noise_freq=freq, nfmin_db=nfmin_db_random, gamma_opt=g_opt_random, rn=rn_random)\n",
    "\n",
    "# Define the save location\n",
    "formatted_filepath = Path(f\"test_noisy_network_formatted.s{ports}p\")\n",
    "\n",
    "# Save the Network as a touchstone file using the string formatting options\n",
    "print(\n",
    "    noisy_ntwk.write_touchstone(\n",
    "        formatted_filepath,\n",
    "        form=\"db\",\n",
    "        return_string=True,\n",
    "        format_spec_freq=freq_fmt,\n",
    "        format_spec_A=data_fmt,\n",
    "        format_spec_B=data_fmt,\n",
    "        format_spec_nf_freq=freq_fmt,\n",
    "        format_spec_nf_min=data_fmt,\n",
    "        format_spec_g_opt_mag=data_fmt,\n",
    "        format_spec_g_opt_phase=data_fmt,\n",
    "        format_spec_rn=data_fmt,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "f9c1ad921755d07784f600fc7c2c11a8933ade33898d5981f5e318f268234d48"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}